﻿Imports System
Imports System.Collections.Generic
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Data
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Media.Imaging
Imports System.Windows.Navigation
Imports System.Windows.Shapes
Imports OMANE.Common.UI
Imports System.CodeDom.Compiler
Imports System.CodeDom
Imports ICSharpCode.AvalonEdit.Highlighting
Imports ICSharpCode.AvalonEdit.Document
Imports Microsoft.Practices.Prism.Commands

Partial Public Class ViewParametres
    Public Sub New()
        MyBase.New()

        Me.InitializeComponent()

        'Dim p1 As ModelParamValue = 1.3
        'Dim p2 As ModelParamValue = {1.5, 0.7}
        'Dim p3 = p1 * p2
        '' Insert code required on object creation below this point.
    End Sub
End Class
<Serializable()> _
Public Class ModelParamType
    Inherits ViewModelBase
    Sub New()

    End Sub

    Protected Friend Overridable Function GetXml() As XElement
        Return <Parameter
                   Name=<%= Name %>
                   UType=<%= UnderlyingType %>
                   Format=<%= Format %>
                   Extras=<%= {IsCalculable, IsFixed, IsMatrix,
                              IsSegmentable, IsSheet, IsSingleton,
                              IsTable, IsUnique, IsVector} %>>

                   <%= Constraint %>

               </Parameter>
    End Function



    Private _Format As String
    Public Property Format As String
        Get
            Return _Format
        End Get
        Set(ByVal value As String)
            OnPropertyChanging("Format")
            _Format = value
            OnPropertyChanged("Format")
        End Set
    End Property

    Private _Legend As String
    Public Property Legend As String
        Get
            Return If(String.IsNullOrEmpty(_Legend), _Name, _Legend)
        End Get
        Set(ByVal value As String)
            OnPropertyChanging("Legend")
            _Legend = value
            OnPropertyChanged("Legend")
        End Set
    End Property


    Private _UnderlyingType As ModelParamUnderLyingType
    Public Property UnderlyingType As ModelParamUnderLyingType
        Get
            Return _UnderlyingType
        End Get
        Set(ByVal value As ModelParamUnderLyingType)
            OnPropertyChanging("UnderlyingType")
            _UnderlyingType = value
            OnPropertyChanged("UnderlyingType")
            UpdateCode()
        End Set
    End Property

    Private _IsSingleton As Boolean
    Public Property IsSingleton As Boolean
        Get
            Return _IsSingleton
        End Get
        Set(ByVal value As Boolean)
            OnPropertyChanging("IsSingleton")
            _IsSingleton = value
            OnPropertyChanged("IsSingleton")
            UpdateCode()
        End Set
    End Property

    Private _IsSegmentable As Boolean
    Public Property IsSegmentable As Boolean
        Get
            Return _IsSegmentable
        End Get
        Set(ByVal value As Boolean)
            OnPropertyChanging("IsSegmentable")
            _IsSegmentable = value
            If value Then
                IsUnique = True
                IsTable = False
            End If
            OnPropertyChanged("IsSegmentable")
            UpdateCode()
        End Set
    End Property

    Private _IsUnique As Boolean
    Public Property IsUnique As Boolean
        Get
            Return _IsUnique
        End Get
        Set(ByVal value As Boolean)
            OnPropertyChanging("IsUnique")
            _IsUnique = value
            OnPropertyChanged("IsUnique")
            UpdateCode()
        End Set
    End Property

    Private _IsVector As Boolean
    Public Property IsVector As Boolean
        Get
            Return _IsVector
        End Get
        Set(ByVal value As Boolean)
            OnPropertyChanging("IsVector")
            _IsVector = value
            OnPropertyChanged("IsVector")
            UpdateCode()
        End Set
    End Property

    Private _IsMatrix As Boolean
    Public Property IsMatrix As Boolean
        Get
            Return _IsMatrix
        End Get
        Set(ByVal value As Boolean)
            OnPropertyChanging("IsMatrix")
            _IsMatrix = value
            OnPropertyChanged("IsMatrix")
            UpdateCode()
        End Set
    End Property

    Private _IsTable As Boolean
    Public Property IsTable As Boolean
        Get
            Return _IsTable
        End Get
        Set(ByVal value As Boolean)
            OnPropertyChanging("IsTable")
            _IsTable = value
            OnPropertyChanged("IsTable")
            UpdateCode()
        End Set
    End Property

    Private _IsFixed As Boolean
    Public Property IsFixed As Boolean
        Get
            Return _IsFixed
        End Get
        Set(ByVal value As Boolean)
            OnPropertyChanging("IsFixed")
            _IsFixed = value
            OnPropertyChanged("IsFixed")
            UpdateCode()
        End Set
    End Property

    Private _IsCalculable As Boolean
    Public Property IsCalculable As Boolean
        Get
            Return _IsCalculable
        End Get
        Set(ByVal value As Boolean)
            OnPropertyChanging("IsCalculable")
            _IsCalculable = value
            OnPropertyChanged("IsCalculable")
            UpdateCode()
        End Set
    End Property

    Private _IsSheet As Boolean
    Public Property IsSheet As Boolean
        Get
            Return _IsSheet
        End Get
        Set(ByVal value As Boolean)
            OnPropertyChanging("IsSheet")
            _IsSheet = value
            OnPropertyChanged("IsSheet")
            UpdateCode()
        End Set
    End Property

    Private _Name As String
    Public Property Name As String
        Get
            Return _Name
        End Get
        Set(ByVal value As String)
            OnPropertyChanging("Name")
            _Name = value
            OnPropertyChanged("Name")
            UpdateCode()
        End Set
    End Property

    Private _Constraint As String
    Public Property Constraint As String
        Get
            Return _Constraint
        End Get
        Set(ByVal value As String)
            OnPropertyChanging("Constraint")
            _Constraint = value
            OnPropertyChanged("Constraint")
            UpdateCode()
        End Set
    End Property

    Private _Code As String
    Public Property Code As String
        Get
            Return _Code
        End Get
        Set(ByVal value As String)
            OnPropertyChanging("Code")
            _Code = value
            OnPropertyChanged("Code")
        End Set
    End Property

    Private _AutoGenerateCode As Boolean = False
    Public Property AutoGenerateCode As Boolean
        Get
            Return _AutoGenerateCode
        End Get
        Set(ByVal value As Boolean)
            OnPropertyChanging("AutoGenerateCode")
            _AutoGenerateCode = value
            OnPropertyChanged("AutoGenerateCode")
        End Set
    End Property

    Private Sub UpdateCode()
        If AutoGenerateCode Then
            Code = GetCode(New VBCodeProvider())
        End If
    End Sub

    Public Function GetCode(ByVal provider As CodeDomProvider) As String
        Dim ns As New CodeNamespace("OMANE.Modules.Builder.Generated.Parameters")

        Dim t As New CodeTypeDeclaration(Name & "_Class")
        Dim utype = GetTypeFromUnderLyingType(Me.UnderlyingType)
        '      Dim basetype = GetType(ModelParameter(Of )).MakeGenericType(utype)
        '     t.BaseTypes.Add(basetype)

        If IsSegmentable Then
            Dim addvarsmethod = New CodeMemberMethod()
            addvarsmethod.Name = "AddVars"
            addvarsmethod.Attributes = MemberAttributes.Public
            Dim varparam = New CodeParameterDeclarationExpression(GetType(String()), "variables")
            varparam.CustomAttributes.Add( _
                New CodeAttributeDeclaration(New CodeTypeReference(GetType(ParamArrayAttribute))))
            addvarsmethod.Parameters.Add(varparam)
            addvarsmethod.ReturnType = Nothing

            Dim removevarsmethod = New CodeMemberMethod()
            removevarsmethod.Name = "RemoveVars"
            removevarsmethod.Attributes = MemberAttributes.Public
            varparam = New CodeParameterDeclarationExpression(GetType(String()), "variables")
            varparam.CustomAttributes.Add( _
                New CodeAttributeDeclaration(New CodeTypeReference(GetType(ParamArrayAttribute))))
            removevarsmethod.Parameters.Add(varparam)
            removevarsmethod.ReturnType = Nothing

            Dim varsdata = New CodeMemberProperty()
            varsdata.Name = "Data"
            varsdata.Attributes = MemberAttributes.Public
            varsdata.HasGet = True
            varsdata.HasSet = False

            varsdata.Type = New CodeTypeReference(GetType(System.Data.DataView))


            t.Members.Add(addvarsmethod)
            t.Members.Add(removevarsmethod)
            t.Members.Add(varsdata)
        End If

        If IsUnique Then
            Dim varsdata = New CodeMemberProperty()
            varsdata.Name = "Value"
            varsdata.Attributes = MemberAttributes.Public
            varsdata.HasGet = True
            varsdata.HasSet = True

            varsdata.Type = utype

            t.Members.Add(varsdata)
        End If

        If IsVector Then

            Dim varsdata = New CodeMemberProperty()
            varsdata.Name = "Value"
            varsdata.Attributes = MemberAttributes.Public
            varsdata.HasGet = True
            varsdata.HasSet = True
            varsdata.Parameters.Add( _
                 New CodeParameterDeclarationExpression(GetType(Integer), "index"))
            varsdata.Type = utype

            Dim vars2data = New CodeMemberProperty()
            vars2data.Name = "Value"
            vars2data.Attributes = MemberAttributes.Public
            vars2data.HasGet = True
            vars2data.HasSet = True
            vars2data.Parameters.Add( _
                 New CodeParameterDeclarationExpression(GetType(Integer), "startindex"))
            vars2data.Parameters.Add( _
                New CodeParameterDeclarationExpression(GetType(Integer), "endindex"))

            vars2data.Type = New CodeTypeReference(GetType(Object)) '(GetType(Vector(Of )), .MakeGenericType(utype))

            t.Members.Add(varsdata)
            t.Members.Add(vars2data)
        End If

        If IsCalculable Then
            Dim computemethod = New CodeMemberMethod()
            computemethod.Name = "Compute"
            computemethod.Attributes = MemberAttributes.Public
            computemethod.ReturnType = Nothing

            t.Members.Add(computemethod)
        End If

        If UnderlyingType = ModelParamUnderLyingType.Case Then
            If Not String.IsNullOrEmpty(Constraint) Then

                If Constraint.Trim().StartsWith("=") Then
                    Dim computemethod = New CodeMemberMethod()
                    computemethod.Name = "ExtractValues"
                    computemethod.Attributes = MemberAttributes.Family
                    computemethod.ReturnType = Nothing
                    t.Members.Add(computemethod)
                Else
                    Dim values = Constraint.Split(New String() {";"}, StringSplitOptions.RemoveEmptyEntries)

                    Dim valuenums = New CodeTypeDeclaration("Cases")
                    valuenums.IsEnum = True
                    valuenums.Attributes = MemberAttributes.Public

                    For Each elt In values
                        If Not String.IsNullOrEmpty(elt.Trim()) Then
                            valuenums.Members.Add(
                                New CodeMemberField(GetType(Integer), elt.Trim()))
                        End If
                    Next

                    t.Members.Add(valuenums)

                End If
            End If
        End If
        ns.Types.Add(t)

        Dim strwriter = New IO.StringWriter()
        Dim options = New CodeGeneratorOptions()
        options.BlankLinesBetweenMembers = True
        provider.GenerateCodeFromNamespace(ns, strwriter, options)
        Dim result = strwriter.ToString()
        strwriter.Dispose()
        Return result
    End Function

    Private Function GetTypeFromUnderLyingType(ByVal utype As ModelParamUnderLyingType) As CodeTypeReference
        Select Case utype
            Case ModelParamUnderLyingType.Boolean
                Return New CodeTypeReference(GetType(Boolean))
            Case ModelParamUnderLyingType.Case
                Dim result = New CodeTypeReference(Name & "." & "Cases")
                Return result
            Case ModelParamUnderLyingType.Date
                Return New CodeTypeReference(GetType(DateTime))
            Case ModelParamUnderLyingType.Double
                Return New CodeTypeReference(GetType(Double))
            Case ModelParamUnderLyingType.Mixed
                Return New CodeTypeReference(GetType(Object))
            Case ModelParamUnderLyingType.Time
                Return New CodeTypeReference(GetType(TimeSpan))
            Case ModelParamUnderLyingType.Uncertain
                Return New CodeTypeReference(GetType(UncertainValue))

        End Select

        Return New CodeTypeReference(GetType(Object))
    End Function
End Class

'Public Class ModelParamValue
'    Private values() As Double

'    Public Shared Widening Operator CType(ByVal source As Double) As ModelParamValue

'    End Operator
'    Public Shared Widening Operator CType(ByVal source As Integer) As ModelParamValue

'    End Operator
'    Public Shared Widening Operator CType(ByVal source As Boolean) As ModelParamValue

'    End Operator
'    Public Shared Widening Operator CType(ByVal source() As Double) As ModelParamValue

'    End Operator
'    Public Shared Widening Operator CType(ByVal source() As Integer) As ModelParamValue

'    End Operator
'    Public Shared Widening Operator CType(ByVal source() As Boolean) As ModelParamValue

'    End Operator
'    Public Shared Widening Operator CType(ByVal source(,) As Double) As ModelParamValue

'    End Operator
'    Public Shared Widening Operator CType(ByVal source(,) As Integer) As ModelParamValue

'    End Operator
'    Public Shared Widening Operator CType(ByVal source(,) As Boolean) As ModelParamValue

'    End Operator
'    Public Shared Operator -(ByVal left As ModelParamValue, ByVal right As ModelParamValue) As ModelParamValue

'    End Operator
'    Public Shared Operator +(ByVal left As ModelParamValue, ByVal right As ModelParamValue) As ModelParamValue

'    End Operator
'    Public Shared Operator *(ByVal left As ModelParamValue, ByVal right As ModelParamValue) As ModelParamValue

'    End Operator
'    Public Shared Operator /(ByVal left As ModelParamValue, ByVal right As ModelParamValue) As ModelParamValue

'    End Operator
'    Public Shared Operator ^(ByVal left As ModelParamValue, ByVal right As ModelParamValue) As ModelParamValue

'    End Operator
'    Public Shared Operator Mod(ByVal left As ModelParamValue, ByVal right As ModelParamValue) As ModelParamValue

'    End Operator
'    Public Shared Operator >>(ByVal left As ModelParamValue, ByVal right As Integer) As ModelParamValue

'    End Operator

'End Class
Public Class Formula

End Class

Public Enum ModelParamUnderLyingType
    [Mixed]
    [Double]
    [Boolean]
    [Time]
    [Date]
    [Case]
    [Uncertain]
End Enum

Partial Public Class ViewModelParametres
    Inherits ViewModelBase
    Implements IViewModelTabSection

    Sub New()
        Title = "PARAMETRES"
    End Sub

    Public Property Icone As String Implements Common.UI.IViewModelTabSection.Icone
    Public Property Title As String Implements Common.UI.IViewModelTabSection.Title


    Private _Params As New ObjectModel.ObservableCollection(Of ModelParamType)
    Public Property Params As ObjectModel.ObservableCollection(Of ModelParamType)
        Get
            Return _Params
        End Get
        Set(ByVal value As ObjectModel.ObservableCollection(Of ModelParamType))
            OnPropertyChanging("Params")
            _Params = value
            OnPropertyChanged("Params")
        End Set
    End Property

    Private _AddParamCommand As New DelegateCommand(Of Object)(AddressOf AddParamExecute)
    Public ReadOnly Property AddParamCommand As DelegateCommand(Of Object)
        Get
            Return _AddParamCommand
        End Get
    End Property
    Private Sub AddParamExecute(ByVal parameter As Object)
        _Params.Add(New ModelParamType() With { _
            .Name = "param_" & Generated(), _
            .UnderlyingType = ModelParamUnderLyingType.Double, _
            .IsSegmentable = True})
    End Sub

    Private _GenerateCodeCommand As New DelegateCommand(Of Object)(AddressOf GenerateCodeExecute)
    Public ReadOnly Property GenerateCodeCommand As DelegateCommand(Of Object)
        Get
            Return _GenerateCodeCommand
        End Get
    End Property
    Private Sub GenerateCodeExecute(ByVal parameter As Object)
        Dim provider = New VBCodeProvider()
        For Each m In Params
            m.Code = m.GetCode(provider)
        Next
    End Sub


    Private genid As Integer = 0
    Private Function Generated() As String
        genid += 1
        Return genid
    End Function



End Class

Public MustInherit Class ModelParameter

    Protected LastState As Object
    Protected CurrentState As Object

End Class

Public MustInherit Class ModelParameter(Of T)
    Inherits ModelParameter

    Protected Overridable Function Validate() As Object

    End Function
End Class

Public Interface ISupportUnique(Of T)
    Property Value As T
End Interface



Public Interface ISupportVector(Of T)
    Property Value(ByVal index As Integer) As T
End Interface


Public Structure UncertainValue
    Public Mean As Double
    Public StDev As Double


    Sub New(ByVal Mean As Double, ByVal StDev As Double)
        Me.Mean = Mean
        Me.StDev = StDev
    End Sub
    Public Overrides Function GetHashCode() As Integer
        Return Mean.GetHashCode() Xor StDev.GetHashCode()
    End Function

    Public Shared Operator -(ByVal x As UncertainValue) As UncertainValue
        Return New UncertainValue(-x.Mean, x.StDev)
    End Operator

    Public Shared Operator +(ByVal left As UncertainValue, ByVal right As UncertainValue) As UncertainValue
        Return New UncertainValue(left.Mean + right.Mean, Math.Sqrt(left.StDev * left.StDev + right.StDev + right.StDev))
    End Operator
    Public Shared Operator +(ByVal left As Double, ByVal right As UncertainValue) As UncertainValue
        Return New UncertainValue(left + right.Mean, right.StDev)
    End Operator
    Public Shared Operator +(ByVal left As UncertainValue, ByVal right As Double) As UncertainValue
        Return New UncertainValue(left.Mean + right, left.StDev)
    End Operator

    Public Shared Operator -(ByVal left As UncertainValue, ByVal right As UncertainValue) As UncertainValue
        Return New UncertainValue(left.Mean - right.Mean, Math.Sqrt(left.StDev * left.StDev + right.StDev + right.StDev))
    End Operator
    Public Shared Operator -(ByVal left As Double, ByVal right As UncertainValue) As UncertainValue
        Return New UncertainValue(left - right.Mean, right.StDev)
    End Operator
    Public Shared Operator -(ByVal left As UncertainValue, ByVal right As Double) As UncertainValue
        Return New UncertainValue(left.Mean - right, left.StDev)
    End Operator

    Public Shared Operator =(ByVal left As UncertainValue, ByVal right As UncertainValue) As Boolean
        Return (left.Mean = right.Mean) And (left.StDev = right.StDev)
    End Operator
    Public Shared Operator <>(ByVal left As UncertainValue, ByVal right As UncertainValue) As Boolean
        Return left.Mean <> right.Mean Or left.StDev <> right.StDev
    End Operator


End Structure

Public Structure WeightedValue
    Public Value As Double
    Public Weight As Double

    Sub New(ByVal Value As Double)
        Me.Value = Value
        Me.Weight = 1.0
    End Sub
    Sub New(ByVal Value As Double, ByVal Weight As Double)
        Me.Value = Value
        Me.Weight = If(Weight > 1.0, 1.0, If(Weight < 0.0, 0.0, Weight))
    End Sub

    Public Shared Widening Operator CType(ByVal v As Double) As WeightedValue
        Return New WeightedValue(v)
    End Operator
End Structure


Public Class HighlightingDefinitionConverter
    Implements IValueConverter



    Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
        Return HighlightingManager.Instance.GetDefinitionByExtension(".vb")
    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Throw New NotImplementedException()
    End Function
End Class

Public Class DocumentConverter
    Implements IValueConverter

    Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
        If value Is Nothing Then
            Return New TextDocument()
        End If
        If String.IsNullOrEmpty(value.ToString()) Then
            Return New TextDocument()
        End If
        Return New TextDocument(value.ToString())
    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Throw New NotImplementedException()
    End Function
End Class


